<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>constructor</title>
</head>

<body>
    <p>
        constructor 属性<br>
        在哪里？ 每个原型对象里面都有个constructor 属性（constructor 构造函数）<br>
        作用：该属性指向该原型对象的构造函数， 简单理解，就是指向我的爸爸，我是有爸爸的孩子
    </p>
    <p>
        使用场景：<br>
        如果有多个对象的方法，我们可以给原型对象采取对象形式赋值. <br>
        但是这样就会覆盖构造函数原型对象原来的内容，这样修改后的原型对象 constructor 就不再指向当前构造函数了 <br>
        此时，我们可以在修改后的原型对象中，添加一个 constructor 指向原来的构造函数。

    </p>
    <p>
        对象原型<br>
        对象都会有一个属性 proto 指向构造函数的 prototype 原型对象，
        之所以我们对象可以使用构造函数 prototype原型对象的属性和方法，就是因为对象有 proto 原型的存在。<br>
        注意：<br>
        - proto 是JS非标准属性<br>
        - [[prototype]]和proto意义相同<br>
        - 用来表明当前实例对象指向哪个原型对象prototype<br>
        - proto对象原型里面也有一个 constructor属性，指向创建该实例对象的构造函数

    </p>
    <p>
        原型继承<br>
        继承是面向对象编程的另一个特征，通过继承进一步提升代码封装的程度，JavaScript 中大多是借助原型对象实现继承的特性。<br>
        龙生龙、凤生凤、老鼠的儿子会打洞描述的正是继承的含义。

    </p>
    <p>
        原型链<br>
        基于原型对象的继承使得不同构造函数的原型对象关联在一起，
        并且这种关联的关系是一种链状的结构，我们将原型对象的链状结构关系称为原型链

    </p>
    <p>
        ① 当访问一个对象的属性（包括方法）时，首先查找这个对象自身有没有该属性。<br>

        ② 如果没有就查找它的原型（也就是 proto指向的 prototype 原型对象）<br>

        ③ 如果还没有就查找原型对象的原型（Object的原型对象）<br>

        ④ 依此类推一直找到 Object 为止（null）<br>

        ⑤ proto对象原型的意义就在于为对象成员查找机制提供一个方向，或者说一条路线<br>

        ⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

    </p>


    <script>
        // 继续抽取   公共的部分放到原型上
        const Person1 = {
            eyes: 2,
            head: 1
        }
        const Person2 = {
            eyes: 2,
            head: 1
        }
        // 构造函数  new 出来的对象 结构一样，但是对象不一样
        function Person() {
            this.eyes = 2
            this.head = 1
        }
        console.log(new Person);
        console.log(Person);
        console.log(Person.prototype);
        console.log(Person.prototype.constructor);


        // 女人  构造函数   继承  想要 继承 Person
        function Woman() { }
        console.log(Woman);
        console.log(Woman.prototype);
        console.log(Woman.prototype.constructor);

        // Woman 通过原型来继承 Person
        // 父构造函数（父类）   子构造函数（子类）
        // 子类的原型 =  new 父类  
        Woman.prototype = new Person()   // {eyes: 2, head: 1} 
        // 指回原来的构造函数
        Woman.prototype.constructor = Woman

        // 给女人添加一个方法  生孩子
        Woman.prototype.baby = function () {
            console.log('宝贝')
        }
        const red = new Woman()
        console.log(red)
        console.log(Woman.prototype)
        // 男人 构造函数  继承  想要 继承 Person
        function Man() { }
        // 通过 原型继承 Person
        Man.prototype = new Person()
        // 指回原来的构造函数
        Man.prototype.constructor = Man
        const pink = new Man()
        console.log(pink)



        //原型链
        function Objetc() { }
        console.log(Object);
        console.log(Object.prototype)
        console.log(Object.prototype.__proto__) // null
        function Person3() {
        }
        const ldh = new Person3()
        console.log(ldh.__proto__ === Person.prototype) // false
        console.log(Person.prototype.__proto__ === Object.prototype) // true
        console.log(ldh instanceof Person3) // true
        console.log(ldh instanceof Object) // true
        console.log(ldh instanceof Array) // false
        console.log([1, 2, 3] instanceof Array) // true
        console.log(Array instanceof Object) // true

    </script>
</body>

</html>